# 面向对象的三个基本特征：封装，继承，多态。
# 多态：对不同的类的对象使用同样的操作。
# 封装：对外部世界隐藏对象的工作细节。
# 继承：以普通的类为基础类建立专门的类对象。
# 构造方法：在实例化时做的一些初始化工作。
# 析构函数：在实例销毁时，执行的一些操作,，通常用于做一些收尾的工作，关闭一些数据库连接或者关闭打开的临时文件。

class People:
    addr = 'Earth'  # 类变量，类变量是类的各个实例共有的属性。当然这个属性也可以放在构造函数中，在每个实例初始化的时候，就会自动生成这个属性。

    def __init__(self, country, name, age=23):  # 构造方法
        self.country = country  # 实例公有属性
        self.name = name
        self.__age = age  # 私有属性

    def __del__(self):  # 析构函数
        print('%s has died' % self.name)

    def get_info(self):  # 实例方法
        print('The %s info'.center(50, '-') % self.name)
        print(f'The {self.name} comes from {self.country} is {self.__age} old')
        print('The {0} comes from {1} is {2} old'.format(
            self.name, self.country, self.__age))

    @classmethod
    def play(cls):  # 类方法
        print('类方法：第一个参数，一般命名为cls，区别于self')

    @staticmethod
    def say():  # 静态方法
        print('静态方法：不需要第一个参数表示自身或者类')


if __name__ == '__main__':
    a = People('China', 'Daniel', 12)  # 实例化一个类时，这时候构造函数会自动执行
    a.get_info()  # 通过实例访问类中的实例方法
    print(a.country)  # 访问实例属性
    # print(a.__age)  # 无法访问
    print(a._People__age)  # 私有属性的访问方法，实例化名._类名__私有属性名
    del a  # 使用del删除了实例a，然后会自动返回析构函数执行的结果。

    A = People('China', 'Alisa', 10)
    A.get_info()
    A.country = 'OOP'  # 可以通过实例修改对应的属性值
    print(A.country)
    del A.country  # 可以通过del删除某个属性
    # A.get_info()  # 报错，没有对应的country属性
    A.country = 'China'  # 添加属性
    A.get_info()
    A.pos = 'signal'
    print(A.pos)
    print(A.addr)  # 访问类变量，相同名称的实例属性会屏蔽类属性
    People.addr = 'Moon'  # 修改类变变量
    del A

    B = People('Chinese', 'Alic', 14)
    B.get_info()
    print(B.addr)

    # 调用类方法：不需要实例化，可通过类直接访问
    People.play()
    # 调用静态方法：不需要实例化，可通过类直接访问
    People.say()
    B.say()
